package com.google.code.swingonfire.component.calendarclock;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.io.Serializable;

import com.google.code.swingonfire.component.calendar.JCalendar;
import com.google.code.swingonfire.component.clock.JClock;
import com.google.code.swingonfire.layout.LayoutUtils;

public class JCalendarClockLayout implements LayoutManager2, Serializable
{

    private static final long serialVersionUID = -7306253387525506357L;

    private final int spacing;

    private Component calendar = null;
    private Component clock = null;

    public JCalendarClockLayout(int spacing)
    {
        super();

        this.spacing = spacing;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addLayoutComponent(String name, Component component)
    {
        if (component instanceof JCalendar)
        {
            if (calendar != null)
            {
                throw new IllegalArgumentException("Duplicate calendar");
            }

            calendar = component;
        }
        else if (component instanceof JClock)
        {
            if (clock != null)
            {
                throw new IllegalArgumentException("Duplicate clock");
            }

            clock = component;
        }
        else
        {
            throw new IllegalArgumentException("Unsupported component " + component.getClass());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addLayoutComponent(Component component, Object constraints)
    {
        addLayoutComponent((String) null, component);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeLayoutComponent(Component component)
    {
        if (calendar == component)
        {
            calendar = null;
        }

        if (clock == component)
        {
            clock = null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Dimension minimumLayoutSize(Container parent)
    {
        Dimension calendarMinimumSize = calendar.getMinimumSize();
        Dimension clockMinimumSize = clock.getMinimumSize();

        return new Dimension(LayoutUtils.add(calendarMinimumSize.width,
            LayoutUtils.add(clockMinimumSize.width, spacing)), Math.max(calendarMinimumSize.height,
            clockMinimumSize.height));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Dimension preferredLayoutSize(Container parent)
    {
        Dimension calendarPreferredSize = calendar.getPreferredSize();
        Dimension clockPreferredSize = clock.getPreferredSize();

        return new Dimension(LayoutUtils.add(calendarPreferredSize.width,
            LayoutUtils.add(clockPreferredSize.width, spacing)), Math.max(calendarPreferredSize.height,
            clockPreferredSize.height));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Dimension maximumLayoutSize(Container target)
    {
        Dimension calendarMaximumSize = calendar.getMaximumSize();
        Dimension clockMaximumSize = clock.getMaximumSize();

        return new Dimension(LayoutUtils.add(calendarMaximumSize.width,
            LayoutUtils.add(clockMaximumSize.width, spacing)), Math.max(calendarMaximumSize.height,
            clockMaximumSize.height));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void layoutContainer(Container parent)
    {
        synchronized (parent.getTreeLock())
        {
            Dimension size = parent.getSize();
            Insets insets = parent.getInsets();

            int width = size.width - insets.left - insets.right - spacing;
            int height = size.height - insets.top - insets.bottom;

            int clockDiameter = height;

            if (clockDiameter > (width / 2))
            {
                clockDiameter = width / 2;
            }

            int calendarWidth = width - clockDiameter - spacing;

            Rectangle bounds = new Rectangle(insets.left, insets.top, calendarWidth, height);

            calendar.setBounds(LayoutUtils.fit(bounds, calendar));

            bounds.x += bounds.width + spacing;
            bounds.width = clockDiameter;

            clock.setBounds(LayoutUtils.fit(bounds, clock));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public float getLayoutAlignmentX(Container target)
    {
        return 0.5f;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public float getLayoutAlignmentY(Container target)
    {
        return 0.5f;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void invalidateLayout(Container target)
    {
        // intentionally left blank
    }

}
